/*
 *  Copyright 2019-2020 Zheng Jie
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package me.zhengjie.suli.tasks.service.impl;

import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.modules.system.domain.DictDetail;
import me.zhengjie.modules.system.repository.DictDetailRepository;
import me.zhengjie.suli.document.domain.Tray;
import me.zhengjie.suli.document.repository.TrayRepository;
import me.zhengjie.suli.inventory.domain.Inventory;
import me.zhengjie.suli.inventory.repository.InventoryRepository;
import me.zhengjie.suli.inventory.service.InventoryService;
import me.zhengjie.suli.location.domain.Location;
import me.zhengjie.suli.location.repository.LocationRepository;
import me.zhengjie.suli.outHouse.domain.OrderDetail;
import me.zhengjie.suli.outHouse.domain.Orders;
import me.zhengjie.suli.outHouse.repository.OrderDetailRepository;
import me.zhengjie.suli.outHouse.repository.OrdersRepository;
import me.zhengjie.suli.outHouse.service.OrdersService;
import me.zhengjie.suli.tasks.domain.TaskDetail;
import me.zhengjie.suli.tasks.domain.Tasks;
import me.zhengjie.suli.tasks.repository.TaskDetailRepository;
import me.zhengjie.suli.tasks.repository.TasksRepository;
import me.zhengjie.suli.tasks.service.TasksService;
import me.zhengjie.suli.tasks.service.dto.TasksDto;
import me.zhengjie.suli.tasks.service.dto.TasksQueryCriteria;
import me.zhengjie.suli.tasks.service.mapstruct.TasksMapper;
import me.zhengjie.suli.toHouse.domain.Receipt;
import me.zhengjie.suli.toHouse.domain.ReceiptDetail;
import me.zhengjie.suli.toHouse.repository.ReceiptDetailRepository;
import me.zhengjie.suli.toHouse.repository.ReceiptRepository;
import me.zhengjie.suli.toHouse.service.ReceiptService;
import me.zhengjie.suli.wcs.domain.AgvTaskDetail;
import me.zhengjie.suli.wcs.domain.AgvTasks;
import me.zhengjie.suli.wcs.repository.AgvTaskDetailRepository;
import me.zhengjie.suli.wcs.repository.AgvTasksRepository;
import me.zhengjie.util.CommonUtil;
import me.zhengjie.util.UuidUtil;
import me.zhengjie.util.Variable;
import me.zhengjie.utils.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.*;

/**
 * @author Allen Gao
 * @website https://eladmin.vip
 * @description 服务实现
 * @date 2022-12-30
 **/
@Service
@RequiredArgsConstructor
@Slf4j
public class TasksServiceImpl implements TasksService {
    @Autowired
    private InventoryRepository inventoryRepository;
    @Autowired
    private LocationRepository locationRepository;
    @Autowired
    private ReceiptRepository receiptRepository;
    @Autowired
    private ReceiptDetailRepository receiptDetailRepository;

    private final TasksRepository tasksRepository;
    private final TaskDetailRepository taskDetailRepository;
    private final TasksMapper tasksMapper;
    private final OrdersRepository ordersRepository;
    private final OrderDetailRepository orderDetailRepository;
    private final InventoryService inventoryService;
    private final AgvTasksRepository agvTasksRepository;
    private final AgvTaskDetailRepository agvTaskDetailRepository;


    @Autowired
    @Lazy
    private ReceiptService receiptService;
    @Autowired
    private CommonUtil commonUtil;


    @Override
    public Map<String, Object> queryAll(TasksQueryCriteria criteria, Pageable pageable) {
        Page<Tasks> page = tasksRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder), pageable);
        return PageUtil.toPage(page.map(tasksMapper::toDto));
    }

    @Override
    public List<TasksDto> queryAll(TasksQueryCriteria criteria) {
        return tasksMapper.toDto(tasksRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder)));
    }

    @Override
    @Transactional
    public TasksDto findById(String id) {
        Tasks tasks = tasksRepository.findById(id).orElseGet(Tasks::new);
        ValidationUtil.isNull(tasks.getId(), "Tasks", "id", id);
        return tasksMapper.toDto(tasks);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public TasksDto create(Tasks resources) {
        resources.setId(IdUtil.simpleUUID());
        return tasksMapper.toDto(tasksRepository.save(resources));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(Tasks resources) {
        Tasks tasks = tasksRepository.findById(resources.getId()).orElseGet(Tasks::new);
        ValidationUtil.isNull(tasks.getId(), "Tasks", "id", resources.getId());
        tasks.copy(resources);
        tasksRepository.save(tasks);
    }

    @Override
    public void deleteAll(String[] ids) {
        for (String id : ids) {
            tasksRepository.deleteById(id);
            List<TaskDetail> taskDetailList = taskDetailRepository.getTaskDetailsByTaskId(id);
            taskDetailRepository.deleteAll(taskDetailList);
        }
    }

    @Override
    public void download(List<TasksDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (TasksDto tasks : all) {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("任务类型", tasks.getTaskType());
            map.put("任务状态", tasks.getStatus());
            map.put("物料", tasks.getElName());
            map.put("起始位置", tasks.getLocationFrom());
            map.put("目标位置", tasks.getLocationTo());
            map.put("载具", tasks.getTrayCode());
            map.put("单位", tasks.getElUnit());
            map.put("数量", tasks.getMtQty());
            map.put("源单编码", tasks.getSourceCode());
            map.put("开始时间", tasks.getStartTime());
            map.put("结束时间", tasks.getEndTime());
            map.put("备注", tasks.getRemark());
            map.put("创建用户", tasks.getCreateBy());
            map.put("修改用户", tasks.getUpdateBy());
            map.put("创建日期", tasks.getCreateTime());
            map.put("修改日期", tasks.getUpdateTime());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    @Override
    public String manualCompletion(List<String> taskId) {
        List<Tasks> allById = tasksRepository.findAllById(taskId);
        List<JSONObject> jsonObjectList = new ArrayList<>();
        for (Tasks tasks : allById) {
            tasks.setStatus(2);
            if (tasks.getTaskType().equals("carry")) {
                OrderDetail byOrderDetailCode = orderDetailRepository.findByOrderDetailCode(tasks.getSourceCode());
                byOrderDetailCode.setStatus(2);
                orderDetailRepository.save(byOrderDetailCode);
                Orders orders = ordersRepository.findById(byOrderDetailCode.getMainId()).orElse(null);
                List<OrderDetail> byMainId = orderDetailRepository.findByMainId(orders.getId());
                boolean wanCheng = true;
                for (OrderDetail orderDetail : byMainId) {
                    if (orderDetail.getStatus() != 2) {
                        wanCheng = false;
                        break;
                    }
                }
                if (wanCheng) {
                    List<TaskDetail> taskDetailsByTaskId = taskDetailRepository.getTaskDetailsByTaskId(tasks.getId());
                    for (TaskDetail taskDetail : taskDetailsByTaskId) {
                        JSONObject jsonObject1 = new JSONObject();
                        jsonObject1.put("pd_list", orders.getSourceDocument());
                        jsonObject1.put("el_no", byOrderDetailCode.getMaterialCode());
                        jsonObject1.put("boxNumber", taskDetail.getPkList());
                        jsonObject1.put("isVmi", taskDetail.getVmiCode());
                        jsonObject1.put("number", taskDetail.getPkQty());
                        jsonObjectList.add(jsonObject1);
                    }

                }
            }
        }
        if (jsonObjectList.isEmpty()) {
            return "1";
        }
        JSONObject jsonObject1 = new JSONObject();
        jsonObject1.put("param", jsonObjectList);
        try {
            commonUtil.httpPost("http://137.40.151.241:9527/WMSExportPD08", jsonObject1);
        } catch (Exception e) {
            log.info(e.getMessage());
        }
        return "2";
    }

    /**
     * Allen Gao 2024-06-05 箱号搜索，未完成，弃用
     */
    @Override
    public List<Tasks> queryTasks(String param) {
        JSONObject jsonObject = JSON.parseObject(param);
        String taskCode = jsonObject.getString("taskCode");
        String boxNumber = jsonObject.getString("boxNumber");
        String queryCondition = getWhereCondition(taskCode, boxNumber);


        return null;
    }

    @Override
    public int reZuPan(String param) {
        JSONObject jsonObject1 = JSON.parseObject(param);
        String id = jsonObject1.getString("id");
        Tasks tasks = tasksRepository.findById(id).orElseGet(null);
        List<TaskDetail> taskDetailList = taskDetailRepository.getTaskDetailsByTaskId(id);
        TaskDetail taskDetail = taskDetailList.get(0);  // 一个载具只能放一个物料箱
        String pkList = taskDetail.getPkList(); // 箱号
        /** 箱号反差入库单明细 */
        ReceiptDetail receiptDetail1 = receiptDetailRepository.getReceiptDetailsByPkList(pkList);

        /** 反查入库单 */
        Receipt receipt = receiptRepository.findById(receiptDetail1.getReceiptId()).orElse(null);

        /** 修改入库明细状态 */
        receiptDetail1.setStatus(0);    //  0--未完成
        receiptDetailRepository.save(receiptDetail1);
        /** 修改入库单 */
        receipt.setActQty(receipt.getActQty().subtract(receiptDetail1.getPkQty())); // 更新入库单的已入库数量
        if (receipt.getActQty().compareTo(new BigDecimal(0)) == 0) {    // 如果修改后的入库数量为0
            receipt.setStatus("0");   // 0--未完成
        } else {
            receipt.setStatus("1"); // 1--部分完成
        }
        receiptRepository.save(receipt);

        /** 修改入库库位状态，以待重新分配 */
        String locationToCode = tasks.getLocationTo();
        Location locationTo = locationRepository.getLocationsByLocationCode(locationToCode);
        locationTo.setStatus(0);    // 0--空闲
        locationRepository.save(locationTo);

        /** 删除AGV任务 */
        AgvTasks agvTasks = agvTasksRepository.findAgvTasksByBillNumber(tasks.getTaskCode());
        if (null != agvTasks) {
            List<AgvTaskDetail> agvTaskDetailByMainId = agvTaskDetailRepository.getAgvTaskDetailByMainId(agvTasks.getId());
            agvTaskDetailRepository.deleteAll(agvTaskDetailByMainId);
            agvTasksRepository.deleteById(agvTasks.getId());
        }

        /** 删除入库任务 */
        tasksRepository.delete(tasks);
        /** 删除入库明细 */
        taskDetailRepository.delete(taskDetail);

        /** 删除库存 */
        Inventory inventory = inventoryRepository.findByBoxNumber(pkList);
        inventoryRepository.delete(inventory);

        return 1;
    }

    /**
     * Allen Gao 2024-06-05 箱号搜索，未完成，弃用
     */
    private String getWhereCondition(String taskCode, String boxNumber) {
        String queryCondition = "";
        if (commonUtil.isStringNotEmpty(taskCode)) {
            if (queryCondition.equals("")) {
                queryCondition = queryCondition + "where task_code like '%" + taskCode + "%'";
            } else {
                queryCondition = queryCondition + " and task_code like '%" + taskCode + "%'";
            }
        }
        if (commonUtil.isStringNotEmpty(boxNumber)) {
            queryCondition = queryCondition + "and id in (select task_id from task_detail where pk_list like '% " + boxNumber + "%')";
        }

        return queryCondition;
    }


    @Override
    public Integer rePush(String param) {
        JSONObject jsonObject = JSON.parseObject(param);
        String sourceCode = jsonObject.getString("sourceCode");
        Tasks tasks = tasksRepository.findBySourceCodeTop(sourceCode);
        if (null != tasks.getStatus() && tasks.getStatus() == 2) {
            return 5;
        }
        if (tasks.getTaskType() == 14) {
            JSONObject freeze = inventoryService.freeze(tasks.getSourceCode());
            if (null == freeze) {
                return 1;
            }
        } else if (tasks.getTaskType() == 15) {
            JSONObject freeze = inventoryService.thaw(tasks.getSourceCode());
            if (null == freeze) {
                return 1;
            }
        } else if (tasks.getTaskType() == 16) {
            JSONObject freeze = inventoryService.free(tasks.getSourceCode());
            if (null == freeze) {
                return 1;
            }
        } else if (tasks.getTaskType() == 17) {
            JSONObject freeze = inventoryService.freeToVmi(tasks.getSourceCode());
            if (null == freeze) {
                return 1;
            }
        }
        return null;
    }

    @Override
    public Integer setOk(String param) {
        try{
            Location location = locationRepository.findByTrayCode(param);
            if (null != location) {
                Tasks tasks = tasksRepository.findByTypeAndTrayCodeAndStatus(param);
                tasks.setStatus(2);
                AgvTasks agvTasks = agvTasksRepository.findAgvTasksByBillNumber(tasks.getTaskCode());
                if (null != agvTasks) {
                    if (null == agvTasks.getStatus() || agvTasks.getStatus() != 2) {
                        agvTasks.setStatus(2);
                        agvTasksRepository.save(agvTasks);
                        tasksRepository.save(tasks);
                        location.setStatus(0);
                        location.setTrayCode("");
                        locationRepository.save(location);
                        return 1;
                    }
                } else {
                    tasksRepository.save(tasks);
                    location.setStatus(0);
                    location.setTrayCode("");
                    locationRepository.save(location);
                    return 1;
                }

            }
            return 2;
        }catch (Exception e){
            return 2;
        }
    }

    @Override
    public Integer setFail(String param) {
        try {
            Location location = locationRepository.findByTrayCode(param);
            if (null != location) {
                Tasks tasks = tasksRepository.findByTypeAndTrayCodeAndStatus(param);
                tasks.setStatus(2);
                AgvTasks agvTasks = agvTasksRepository.findAgvTasksByBillNumber(tasks.getTaskCode());
                if (null != agvTasks){
                    if (null == agvTasks.getStatus() || agvTasks.getStatus() != 2) {
                        agvTasks.setStatus(2);
                        location.setStatus(3);
                        locationRepository.save(location);
                        agvTasksRepository.save(agvTasks);
                        tasksRepository.save(tasks);
                        return 1;
                    }
                }else{
                    location.setStatus(3);
                    locationRepository.save(location);
                    tasksRepository.save(tasks);
                    return 1;
                }

            }
            return 2;
        }catch (Exception e){
            return 2;
        }
    }
}